#pragma once
#include <vector>
#include <stdexcept>
namespace LxCFD
{
    template <typename T>
    class LinkArray
    {
    public:
        struct Node
        {
        public:
            T Value;
            Node *Prev = nullptr;
        };
        struct List
        {
        public:
            struct Iterator
            {
            public:
                inline Iterator(Node *node)
                {
                    _Current = node;
                }
                inline void MovePrev()
                {
                    _Current = _Current->Prev;
                }
                inline bool IsContinue()
                {
                    return _Current != nullptr;
                }
                inline T &GetValue()
                {
                    return _Current->Value;
                }

            protected:
                Node *_Current;
            };

            int Length = 0;
            Node *Last = nullptr;
            inline Iterator GetIterator()
            {
                return Iterator(Last);
            }
            void Clear()
            {
                Length = 0;
                Last = nullptr;
            }
            void AddToVector(std::vector<T> &target)
            {
                target.resize(target.size() + Length);
                int pos = target.size() - 1;
                for (auto ite = GetIterator(); ite.IsContinue(); ite.MovePrev())
                {
                    target.at(pos) = ite.GetValue();
                    --pos;
                }
            }
        };
        ~LinkArray()
        {
            DeleteList();
        }
        void Initialize(int listCapacity, int vectorCapacity)
        {
            DeleteList();
            _StorageList.clear();

            _VectorCapacity = vectorCapacity;
            _StorageList.reserve(listCapacity);
            _StorageList.push_back(new std::vector<Node>());
            _StorageList.back()->reserve(_VectorCapacity);
        }
        void AddNodeToList(List &targetList, const T &value)
        {
            Node *n = RequireStorage();
            n->Value = value;
            n->Prev = targetList.Last;
            targetList.Last = n;
            ++targetList.Length;
        }

    protected:
        int _VectorCapacity = 4096;
        std::vector<std::vector<Node> *> _StorageList;
        Node *RequireStorage()
        {
            {
                std::vector<Node> &lastV1 = *_StorageList.back();
                if (lastV1.size() >= lastV1.capacity())
                {
                    _StorageList.push_back(new std::vector<Node>());
                    _StorageList.back()->reserve(_VectorCapacity);
                }
            }
            {
                std::vector<Node> &lastV2 = *_StorageList.back();
                //Node *result = &(*lastV2.end());
                lastV2.resize(lastV2.size() + 1);
                return &lastV2[lastV2.size() - 1];//result;
            }
        }
        void DeleteList()
        {
            for (int pos = _StorageList.size() - 1; pos >= 0; --pos)
            {
                delete _StorageList.at(pos);
            }
        }
    };
}